#pragma once

#include <algorithm/analytical_model/algorithm/cuda/inter_op/Data.h>

#include <memory>

namespace solar::cuda
{
    class SimplifiedMethod;
}

namespace solar::cuda::inter_op
{
    class SimplifiedMethod
    {
        public:
            SimplifiedMethod(Float3* helio_vertices, Float3* recv_vertices, Float3 helio_normal,
                             Float3 recv_normal, Float3 helio_pos, Float3 target_center,
                             Float3 helio_size, Int2 row_col, float DNI,
                             cudaStream_t stream = nullptr);
            SimplifiedMethod(Float3* helio_vertices, Float3 recv_size, Float3 helio_normal,
                             Float3 recv_pos, Float3 helio_pos, Float3 target_center,
                             Float3 helio_size, Int2 row_col, float DNI, float* d_array = nullptr,
                             cudaStream_t stream = nullptr);
            SimplifiedMethod(Float3* d_image_plane_x_z_axes, Float4* d_center_bias,
                             Float3* d_flux_params, int n, Float3 recv_size, Float3 recv_pos,
                             Int2 row_col, cudaStream_t stream = nullptr);
            // For convenient use only
            SimplifiedMethod() = default;

            /// @brief 绘制平面接收器上的通量图
            void drawFluxMap() const;
            /// @brief 绘制圆柱形接收器上的通量图
            void drawFluxMapCylinder() const;

            void setHelioVertices(Float3* helio_vertices) const;
            void setRecvVertices(Float3* recv_vertices) const;
            void setModelParams(float sigma1, float sigma2, float peak,
                                float correlation = 0) const;
            void setCenterBias(const Float3& bias) const;
            void setShadowBlockFactor(float factor) const;
            /// @brief 获取仿真结果（数据在GPU上）
            [[nodiscard]] auto getFluxMap() const -> float*;
            [[nodiscard]] auto loadNormalDistributionArray() const -> bool;
            [[nodiscard]] auto getCudaStream() const -> cudaStream_t;
            void setCudaStream(const cudaStream_t& stream) const;
            void fakeClearResult() const;
            void fakeClearCudaStream() const;

        private:
            std::shared_ptr<::solar::cuda::SimplifiedMethod> delegate_ptr_;
    };
} // namespace solar::cuda::inter_op
